import uuid

from flask_bcrypt import generate_password_hash, check_password_hash
from marshmallow import fields, validate, EXCLUDE
from sqlalchemy import CHAR, VARCHAR, DateTime, Table, Column, ForeignKey
from models.association_tables import account_role

from config.database import db
from config.marshmallow_config import ma


class Account(db.Model):
    __tablename__ = 'account'

    id = db.Column(VARCHAR(50), primary_key=True, default=lambda: str(uuid.uuid4()))
    username = db.Column(VARCHAR(50), nullable=False)
    password = db.Column(VARCHAR(60), nullable=False)
    enabled = db.Column(CHAR(1), nullable=False)
    email = db.Column(VARCHAR(100), nullable=True)
    mobile = db.Column(VARCHAR(45), nullable=True)
    # role = db.Column(VARCHAR(50), nullable=True)
    name = db.Column(VARCHAR(50), nullable=True)
    avatar = db.Column(VARCHAR(50), nullable=True)
    home_path = db.Column(VARCHAR(50), nullable=True)
    remark = db.Column(VARCHAR(200), nullable=True)
    created_at = db.Column(DateTime, nullable=True)
    updated_at = db.Column(DateTime, nullable=True)

    roles = db.relationship('Role',
                          secondary=account_role,
                          lazy='joined',
                          backref=db.backref('accounts', lazy='dynamic'))

    def hash_password(self):
        self.password = generate_password_hash(self.password).decode('utf8')

    def check_password(self, password):
        return check_password_hash(self.password, password)

    def to_dict(self):
        role = self.roles[0] if self.roles else None
        return {
            'id': self.id,
            'username': self.username,
            'enabled': self.enabled,
            'email': self.email,
            'name': self.name,
            'mobile': self.mobile,
            'avatar': self.avatar,
            'homePath': self.home_path,
            'remark': self.remark,
            'createTime': self.created_at.strftime('%Y-%m-%d %H:%M:%S') if self.created_at else None,
            'updatedAt': self.updated_at.strftime('%Y-%m-%d %H:%M:%S') if self.updated_at else None,
            'roleId': role.id if role else None,
            'role': role.role_name if role else None
        }


class AccountSchema(ma.SQLAlchemyAutoSchema):
    class Meta:
        model = Account
        # 避免传来的数据中有数据库中没有的字段，会报错的问题
        unknown = EXCLUDE
        load_instance = True

    username = fields.String(required=True, validate=validate.Length(min=1, max=50))
    password = fields.String(required=False, validate=validate.Length(min=6, max=60))
    enabled = fields.Boolean(required=True)
    email = fields.Email(required=True, validate=validate.Length(max=100))
    mobile = fields.String(required=True, validate=validate.Length(max=45))
    # role = fields.String(required=False, validate=validate.Length(max=50))
    name = fields.String(required=True, validate=validate.Length(max=50))
    avatar = fields.String(required=False, validate=validate.Length(max=50))
    home_path = fields.String(required=False, validate=validate.Length(max=50))
    # allow_none 可以接收None
    remark = fields.String(required=False, validate=validate.Length(max=200),allow_none=True)


account_schema = AccountSchema()
accounts_schema = AccountSchema(many=True)
